import { FilterRule } from '#/request';
import { FilterOperateEnum } from '@/enums/filterOperateEnum';
import { getOperateEntities } from '@/utils/common';
import { AdColumn } from '../types/table';

import { getPreferenceInfo } from '@/utils/preference';

/** 更改筛选规则类型 */
export function changeFilterRuleType(rule: FilterRule, column: AdColumn) {
  column.dataType = column.dataType ? column.dataType : 'string';
  switch (column.dataType) {
    case 'enum':
      column.entities = getOperateEntities([FilterOperateEnum.Equal, FilterOperateEnum.NotEqual]);
      column.enumData = column.enumData || [];
      column.formRender = column.formRender ? column.formRender : { name: 'Select' };

      rule.Operate = column.entities[0]?.Operate;
      rule.Value = column.enumData[0]?.value || null;
      break;
    case 'integer':
    case 'number':
    case 'quantity':
    case 'price':
    case 'amount':
    case 'rate':
    case 'percentage':
    case 'measure':
      column.entities = getOperateEntities([
        FilterOperateEnum.Equal,
        FilterOperateEnum.NotEqual,
        FilterOperateEnum.Less,
        FilterOperateEnum.LessOrEqual,
        FilterOperateEnum.Greater,
        FilterOperateEnum.GreaterOrEqual,
      ]);
      const defComponent = column.dataType === 'integer' ? 'Input' : 'InputNumber';
      column.formRender = column.formRender ? column.formRender : { name: defComponent };

      rule.Operate = column.entities[0]?.Operate;
      rule.Value = null;
      break;
    case 'string':
    case 'text':
    case 'password':
    case 'email':
    case 'mobile':
    case 'url':
    case 'ipv4':
    case 'ipv6':
    case 'idcard':
      column.entities = getOperateEntities([
        FilterOperateEnum.Equal,
        FilterOperateEnum.NotEqual,
        FilterOperateEnum.StartsWith,
        FilterOperateEnum.EndsWith,
        FilterOperateEnum.Contains,
        FilterOperateEnum.NotContains,
      ]);
      column.formRender = column.formRender
        ? column.formRender
        : column.dataType === 'password'
          ? { name: 'Input' }
          : { name: 'Input' };

      rule.Operate = FilterOperateEnum.Contains;
      rule.Value = null;
      break;
    case 'guid':
      column.entities = getOperateEntities([FilterOperateEnum.Equal, FilterOperateEnum.NotEqual]);
      column.formRender = column.formRender ? column.formRender : { name: 'Input' };

      rule.Operate = column.entities[0]?.Operate;
      rule.Value = null;
      break;
    case 'boolean':
      column.entities = getOperateEntities([FilterOperateEnum.Equal, FilterOperateEnum.NotEqual]);
      column.formRender = column.formRender ? column.formRender : { name: 'Switch' };

      rule.Operate = column.entities[0]?.Operate;
      rule.Value = rule.Value === true ? true : false;
      break;
    case 'datetime':
    case 'date':
    case 'time':
      column.entities = getOperateEntities([
        FilterOperateEnum.Equal,
        FilterOperateEnum.NotEqual,
        FilterOperateEnum.Less,
        FilterOperateEnum.LessOrEqual,
        FilterOperateEnum.Greater,
        FilterOperateEnum.GreaterOrEqual,
      ]);
      if (!column.editRender) {
        switch (column.dataType) {
          case 'datetime':
          case 'date':
            column.formRender = {
              name: 'DatePicker',
              props: { ...column.formRender?.props, showTime: column.dataType === 'datetime' },
            };
            break;
          case 'time':
            column.formRender = { name: 'TimePicker' };
            break;
        }
      }

      rule.Operate = column.entities[0]?.Operate;
      rule.Value = null;
      break;

    default:
      column.entities = getOperateEntities([
        FilterOperateEnum.Equal,
        FilterOperateEnum.NotEqual,
        FilterOperateEnum.StartsWith,
        FilterOperateEnum.EndsWith,
        FilterOperateEnum.Contains,
        FilterOperateEnum.NotContains,
      ]);
      rule.Operate = FilterOperateEnum.Contains;
      rule.Value = null;
      rule.Control = 'string';
      break;
  }
  switch (column.formRender?.name) {
    case 'Select':
    case 'ApiSelect':
      column.formRender.props = {
        ...column.formRender?.props,
        showSearch: true,
        optionFilterProp: 'label',
        style: { width: '100%' },
      };
      break;
    case 'InputNumber':
      let dataType:
        | 'integer'
        | 'number'
        | 'quantity'
        | 'price'
        | 'amount'
        | 'rate'
        | 'percentage'
        | 'measure' = 'number';
      switch (column.dataType) {
        case 'integer':
        case 'number':
        case 'quantity':
        case 'price':
        case 'amount':
        case 'rate':
        case 'percentage':
        case 'measure':
          dataType = column.dataType;
          break;
      }
      const numberPrecision = getInputNumberPrecision(dataType);
      column.formRender.props = {
        ...column.formRender?.props,
        precision: numberPrecision >= 0 ? numberPrecision : undefined,
        style: { width: '100%' },
      };
      break;
  }
}

/** 获取数值输入框精度 */
export function getInputNumberPrecision(
  inputType:
    | 'integer'
    | 'number'
    | 'quantity'
    | 'price'
    | 'amount'
    | 'rate'
    | 'percentage'
    | 'measure',
) {
  let numberPrecision = -1;
  const preferenceInfo = getPreferenceInfo();
  if (preferenceInfo !== undefined && preferenceInfo !== null) {
    switch (inputType) {
      case 'integer':
        numberPrecision = 0;
        break;
      case 'number':
        numberPrecision = -1;
        break;
      case 'quantity':
        numberPrecision = preferenceInfo.QuantityAccuracy || -1;
        break;
      case 'price':
        numberPrecision = preferenceInfo.PriceAccuracy || -1;
        break;
      case 'amount':
        numberPrecision = preferenceInfo.AmountAccuracy || -1;
        break;
      case 'rate':
        numberPrecision = preferenceInfo.RateAccuracy || -1;
        break;
      case 'percentage':
        numberPrecision = preferenceInfo.PercentageAccuracy || -1;
        break;
      case 'measure':
        numberPrecision = preferenceInfo.MeasureAccuracy || -1;
        break;
    }
  }

  return numberPrecision;
}
